/* test_md2.c
**
** Copyright (c) 2007, Meadhbh S. Hamrick
** All rights reserved.
** 
** Redistribution  and  use  in  source  and  binary  forms,  with  or  without
** modification, are permitted provided that the following conditions are met:
** 
**  * Redistributions of  source code must  retain the above  copyright notice,
**    this list of conditions and the following disclaimer.
** 
**  * Redistributions in binary form must reproduce the above copyright notice,
**    this list of conditions and the following disclaimer in the documentation
**    and/or other materials provided with the distribution.
** 
**  * Neither the  name of  Project Meadhbh  nor the names of  its contributors
**    may be used  to endorse  or promote  products derived from this  software
**    without specific prior written permission.
** 
** THIS SOFTWARE IS PROVIDED BY  THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY  EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT  LIMITED TO, THE
** IMPLIED WARRANTIES  OF MERCHANTABILITY AND FITNESS FOR  A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO  EVENT SHALL THE  COPYRIGHT OWNER OR  CONTRIBUTORS BE
** LIABLE  FOR  ANY  DIRECT,   INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
** CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,  PROCUREMENT  OF
** SUBSTITUTE GOODS  OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
** INTERRUPTION)  HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN
** CONTRACT,  STRICT LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE OR  OTHERWISE)
** ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
** 
** $Id: test_md2.c 52 2007-09-01 05:22:04Z meadhbh.siobhan $
*/

/** \file test_md2.c
**  \brief Test MD2 Cryptographic Hash Functions
**
** This   file   implements   the    tests   that   are   referenced   in
** test_crypto.c.   It  is  assumed   that  the   initalization  function
** suite_md2_init()   will  be   called  before   any  of   the  test_*()
** functions. The initialization function does all the "heavy lifting" of
** creating  contexts  and hashing  test  vectors.  The individual  tests
** simply  compare output and  intermediate values  with known  good test
** values.
** 
** "Canonical"  test  vectors are  provided  in  the  inputs and  outputs
** arrays.  The inputs  array is  an array  of known  strings  that, when
** hashed, are supposed to generate  known values. We're using the values
** from RFC1319, it's as close to authoratative as we could find. To test
** the  hashing  functions,  the  suite_md2_init() function  hashes  each
** string in the inputs array and places the result in the actual_outputs
** array. In the test_md2_rfc_vectors()  function, we simply compare what
** we generated in the actual_outputs array with the known good values in
** the outputs array.
** 
** Numerous  tests for cloning  behavior are  performed. Cloning  is used
** extensively in  these tests.  If it doesn't  work, then  it's unlikely
** that anything  will work. But we perform  a number of tests  to see if
** there are particular problems with cloning before or after various md2
** function calls.
** 
** We test the mc_mic_md2_clear() function by clearing a used context and
** then  comparing it  with a  newly initialized  context. Note  that the
** clear function  simply reinitializes a  context to it's  default state
** rather than zeroing memory.
** 
** The  mc_mic_md2_initialize() function is  tested with  the known-value
** checks mentioned above. We also  verify that memory is properly zeroed
** out.
** 
** Finally,  the mc_mic_md2_update()  function  is tested  by looking  at
** intermediate and final results in md2 contexts.
*/

/* Macro Definitions */
#define MC_MIC_MD2_TEST_MAX_CONTEXTS 20
#define MC_MIC_MD2_TEST_MAX_VECTORS 7

/* File Includes */
#include <string.h>
#include "mutil.h"
#include "mcrypto/md2.h"
#include "test_md2.h"
#include <CUnit/CUnit.h>
#include <stdlib.h>
#include <stdio.h>

/* Typedefs, Structs, Unions, Enums, etc. */

/* Static Function Prototypes */

/* Variable Declarations */
tMCMd2 md2_actual_contexts [ MC_MIC_MD2_TEST_MAX_CONTEXTS ];
tMCMd2 md2_contexts [ MC_MIC_MD2_TEST_MAX_CONTEXTS ] = {
{
  .count = 0x00000000,
  .checksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  .data.asThree = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  }
},
{
  .count = 0x00000000,
  .checksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  .data.asThree = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  }
},
{
  .count = 0x00000000,
  .checksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  .data.asThree = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  }
},
{
  .count = 0x00000000,
  .checksum = { 0x62, 0x38, 0x67, 0xB6, 0xAF, 0x52, 0x79, 0x5E, 0x5F, 0x21, 0x4E, 0x97, 0x20, 0xBE, 0xEA, 0x8D},
  .data.asThree = {
    { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73},
    { 0xBE, 0x2A, 0xF2, 0x6F, 0xA3, 0x00, 0x1F, 0xFC, 0x63, 0x4B, 0x4F, 0x4B, 0x56, 0x5A, 0x7E, 0x27},
    { 0x62, 0x3A, 0x11, 0xE9, 0xC2, 0x0A, 0xB4, 0x22, 0xF1, 0x91, 0xF2, 0x9D, 0xD8, 0xF2, 0x28, 0x9D}
  }
},
{
  .count = 0x00000001,
  .checksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  .data.asThree = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  }
},
{
  .count = 0x00000001,
  .checksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  .data.asThree = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  }
},
{
  .count = 0x00000001,
  .checksum = { 0x19, 0x73, 0x9C, 0xAD, 0xA3, 0xBA, 0x28, 0x16, 0x93, 0x34, 0x8E, 0x9D, 0x25, 0x6F, 0xFF, 0x31},
  .data.asThree = {
    { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1},
    { 0xAB, 0x2B, 0x08, 0x41, 0x8D, 0xBF, 0x33, 0xB8, 0x95, 0x1A, 0x67, 0x73, 0x7F, 0xF2, 0x69, 0x6E},
    { 0xB6, 0x77, 0x6F, 0x58, 0xC7, 0x28, 0xD1, 0xAD, 0xA4, 0xAA, 0xA1, 0x31, 0x06, 0x6F, 0xC7, 0xFC}
  }
},
{
  .count = 0x00000003,
  .checksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  .data.asThree = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x61, 0x62, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  }
},
{
  .count = 0x00000003,
  .checksum = { 0x19, 0xE2, 0x9D, 0x1B, 0x73, 0x04, 0x36, 0x8E, 0x59, 0x5A, 0x27, 0x6F, 0x30, 0x2F, 0x57, 0xCC},
  .data.asThree = {
    { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB},
    { 0x92, 0x65, 0x23, 0xC3, 0x60, 0xDB, 0x68, 0xB1, 0x57, 0xCB, 0x65, 0x63, 0xC3, 0x71, 0xF3, 0x9D},
    { 0x06, 0xFE, 0xFE, 0x8C, 0x6F, 0xAD, 0xE5, 0x6A, 0xF8, 0x86, 0x5D, 0xCD, 0xF2, 0x9E, 0xDB, 0x9E}
  }
},
{
  .count = 0x0000000E,
  .checksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  .data.asThree = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  }
},
{
  .count = 0x0000000E,
  .checksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  .data.asThree = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  }
},
{
  .count = 0x0000000E,
  .checksum = { 0x56, 0xD6, 0x51, 0x57, 0xDE, 0xDF, 0xCD, 0x75, 0xA7, 0xB1, 0xE8, 0x2D, 0x97, 0x0E, 0xEC, 0x4B},
  .data.asThree = {
    { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0},
    { 0x26, 0x31, 0x01, 0xEA, 0xB0, 0xCF, 0x4A, 0x9A, 0xBE, 0x28, 0x12, 0x8D, 0x41, 0xE2, 0x1C, 0x39},
    { 0x5B, 0x17, 0x2E, 0x4A, 0xC7, 0xC0, 0x9F, 0x60, 0xD2, 0xCE, 0xCC, 0xDD, 0xA4, 0xC3, 0x70, 0x0C}
  }
},
{
  .count = 0x00000010,
  .checksum = { 0x19, 0xE2, 0x9D, 0x99, 0x9F, 0x99, 0x83, 0xF8, 0x60, 0x54, 0x7A, 0x73, 0x82, 0xEB, 0x64, 0xC0},
  .data.asThree = {
    { 0x8B, 0x08, 0xF2, 0xB4, 0x66, 0x34, 0x02, 0xAF, 0x2C, 0x48, 0x06, 0x4B, 0x27, 0x80, 0xD0, 0x11},
    { 0xEE, 0xC9, 0xB3, 0x7E, 0x36, 0x3C, 0x3C, 0x90, 0x1E, 0x43, 0x24, 0x9C, 0x86, 0x1D, 0x3A, 0x2C},
    { 0x9D, 0xF1, 0xE4, 0x15, 0x35, 0x12, 0x14, 0x2E, 0x92, 0x06, 0x02, 0x13, 0xF4, 0x1A, 0x95, 0xFD}
  }
},
{
  .count = 0x00000010,
  .checksum = { 0x19, 0xE2, 0x9D, 0x99, 0x9F, 0x99, 0x83, 0xF8, 0x60, 0x54, 0x7A, 0x73, 0x82, 0xEB, 0x64, 0xC0},
  .data.asThree = {
    { 0x8B, 0x08, 0xF2, 0xB4, 0x66, 0x34, 0x02, 0xAF, 0x2C, 0x48, 0x06, 0x4B, 0x27, 0x80, 0xD0, 0x11},
    { 0xEE, 0xC9, 0xB3, 0x7E, 0x36, 0x3C, 0x3C, 0x90, 0x1E, 0x43, 0x24, 0x9C, 0x86, 0x1D, 0x3A, 0x2C},
    { 0x9D, 0xF1, 0xE4, 0x15, 0x35, 0x12, 0x14, 0x2E, 0x92, 0x06, 0x02, 0x13, 0xF4, 0x1A, 0x95, 0xFD}
  }
},
{
  .count = 0x0000001A,
  .checksum = { 0x19, 0xE2, 0x9D, 0x99, 0x9F, 0x99, 0x83, 0xF8, 0x60, 0x54, 0x7A, 0x73, 0x82, 0xEB, 0x64, 0xC0},
  .data.asThree = {
    { 0x8B, 0x08, 0xF2, 0xB4, 0x66, 0x34, 0x02, 0xAF, 0x2C, 0x48, 0x06, 0x4B, 0x27, 0x80, 0xD0, 0x11},
    { 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x24, 0x9C, 0x86, 0x1D, 0x3A, 0x2C},
    { 0x9D, 0xF1, 0xE4, 0x15, 0x35, 0x12, 0x14, 0x2E, 0x92, 0x06, 0x02, 0x13, 0xF4, 0x1A, 0x95, 0xFD}
  }
},
{
  .count = 0x0000001A,
  .checksum = { 0x4A, 0x42, 0xD3, 0xA3, 0x77, 0xB7, 0xE9, 0x98, 0x8F, 0xB9, 0x28, 0x96, 0x99, 0xE4, 0xD3, 0xA3},
  .data.asThree = {
    { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B},
    { 0xBC, 0x08, 0x7F, 0x7D, 0xA3, 0x9D, 0x17, 0x0F, 0x82, 0xB0, 0x0D, 0x9F, 0x65, 0xEA, 0x1A, 0x10},
    { 0x52, 0x7D, 0xF2, 0x59, 0x11, 0xBD, 0xC7, 0x93, 0xEA, 0x67, 0x27, 0x46, 0xFA, 0xF5, 0x55, 0x35}
  }
},
{
  .count = 0x00000000,
  .checksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  .data.asThree = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  }
},
{
  .count = 0x0000001A,
  .checksum = { 0x19, 0xE2, 0x9D, 0x99, 0x9F, 0x99, 0x83, 0xF8, 0x60, 0x54, 0x7A, 0x73, 0x82, 0xEB, 0x64, 0xC0},
  .data.asThree = {
    { 0x8B, 0x08, 0xF2, 0xB4, 0x66, 0x34, 0x02, 0xAF, 0x2C, 0x48, 0x06, 0x4B, 0x27, 0x80, 0xD0, 0x11},
    { 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x24, 0x9C, 0x86, 0x1D, 0x3A, 0x2C},
    { 0x9D, 0xF1, 0xE4, 0x15, 0x35, 0x12, 0x14, 0x2E, 0x92, 0x06, 0x02, 0x13, 0xF4, 0x1A, 0x95, 0xFD}
  }
},
{
  .count = 0x0000001A,
  .checksum = { 0x4A, 0x42, 0xD3, 0xA3, 0x77, 0xB7, 0xE9, 0x98, 0x8F, 0xB9, 0x28, 0x96, 0x99, 0xE4, 0xD3, 0xA3},
  .data.asThree = {
    { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B},
    { 0xBC, 0x08, 0x7F, 0x7D, 0xA3, 0x9D, 0x17, 0x0F, 0x82, 0xB0, 0x0D, 0x9F, 0x65, 0xEA, 0x1A, 0x10},
    { 0x52, 0x7D, 0xF2, 0x59, 0x11, 0xBD, 0xC7, 0x93, 0xEA, 0x67, 0x27, 0x46, 0xFA, 0xF5, 0x55, 0x35}
  }
},
{
  .count = 0x00000000,
  .checksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  .data.asThree = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  }
},
};

uint8_t *md2_inputs [ MC_MIC_MD2_TEST_MAX_VECTORS ] = {
  (uint8_t *) "",
  (uint8_t *) "a",
  (uint8_t *) "abc",
  (uint8_t *) "message digest",
  (uint8_t *) "abcdefghijklmnopqrstuvwxyz",
  (uint8_t *) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
  (uint8_t *) "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
};

uint8_t md2_actual_outputs [ MC_MIC_MD2_TEST_MAX_VECTORS ][16];

uint8_t md2_outputs [ MC_MIC_MD2_TEST_MAX_VECTORS ][16] = {
  { 0x83, 0x50, 0xe5, 0xa3, 0xe2, 0x4c, 0x15, 0x3d,
    0xf2, 0x27, 0x5c, 0x9f, 0x80, 0x69, 0x27, 0x73 },
  { 0x32, 0xec, 0x01, 0xec, 0x4a, 0x6d, 0xac, 0x72,
    0xc0, 0xab, 0x96, 0xfb, 0x34, 0xc0, 0xb5, 0xd1 },
  { 0xda, 0x85, 0x3b, 0x0d, 0x3f, 0x88, 0xd9, 0x9b,
    0x30, 0x28, 0x3a, 0x69, 0xe6, 0xde, 0xd6, 0xbb },
  { 0xab, 0x4f, 0x49, 0x6b, 0xfb, 0x2a, 0x53, 0x0b,
    0x21, 0x9f, 0xf3, 0x30, 0x31, 0xfe, 0x06, 0xb0 },
  { 0x4e, 0x8d, 0xdf, 0xf3, 0x65, 0x02, 0x92, 0xab,
    0x5a, 0x41, 0x08, 0xc3, 0xaa, 0x47, 0x94, 0x0b },
  { 0xda, 0x33, 0xde, 0xf2, 0xa4, 0x2d, 0xf1, 0x39,
    0x75, 0x35, 0x28, 0x46, 0xc3, 0x03, 0x38, 0xcd },
  { 0xd5, 0x97, 0x6f, 0x79, 0xd8, 0x3d, 0x3a, 0x0d,
    0xc9, 0x80, 0x6c, 0x3c, 0x66, 0xf3, 0xef, 0xd8 }
};

/* Function Definitions */

/** \fn int suite_md2_init( void )
**  \brief Calls various md2 functions in preparation for value checking.
**  \returns 0 (success)
** 
** This is  the function where "rubber  meets the road." We  call all the
** functions  under test  in this  initialization function  and  in later
** tests simply compare the values we get with known good values.
** 
** We have  a series of tMCMd2  data structures used to  hold the hashing
** context after  various operations. This function  generally performs a
** function,  then clones  the context.  We do  this to  save information
** about the intermediate state of the hash functions. This can help with
** debugging if something  goes wrong. IT IS NOT  THE GENERAL PATTERN FOR
** USING THIS API.
** 
** The algorithm-specific  functions don't  return error codes  and don't
** check parameters. Ergo, we won't  know if there's a failure during the
** init routine's run. We get that info later in the test_*()
** functions.
*/

int suite_md2_init() {
  /* Initialize the first context */
  mc_mic_md2_initialize( & (md2_actual_contexts[0]) );

  /* Clone a context that has not been used */
  mc_mic_md2_clone( & (md2_actual_contexts[1]), & (md2_actual_contexts[0]) ); 

  /* Clone a context for vector 0 */
  mc_mic_md2_clone( & (md2_actual_contexts[2]), & (md2_actual_contexts[0]) );

  /* Hash Nothing (vector 0) */
  mc_mic_md2_update( & (md2_actual_contexts[2]), (uint8_t *) md2_inputs[ 0 ], (uint32_t) strlen( (const char *) md2_inputs[ 0 ] ) );

  /* Clone this context */
  mc_mic_md2_clone( & (md2_actual_contexts[3]), & (md2_actual_contexts[2]) );

  /* Produce Digest for vector 0 */
  mc_mic_md2_digest( & (md2_actual_contexts[3]), (uint8_t *) md2_actual_outputs[0] );

  /* Clone a context for vector 1 */
  mc_mic_md2_clone( & (md2_actual_contexts[4]), & (md2_actual_contexts[0]) );

  /* Hash "a" (vector 1) */
  mc_mic_md2_update( & (md2_actual_contexts[4]), (uint8_t *) md2_inputs[1], (uint32_t) strlen( (const char *) md2_inputs[1] ) );

  /* Clone a context that has been updated with less than one block, but not
     finalized */
  mc_mic_md2_clone( & (md2_actual_contexts[5]), & (md2_actual_contexts[4]) );

  /* Clone the context for vector 1 prior to calling digest */
  mc_mic_md2_clone( & (md2_actual_contexts[6]), & (md2_actual_contexts[4]) );

  /* Produce digest for vector 1 */
  mc_mic_md2_digest( & (md2_actual_contexts[6]), (uint8_t *) md2_actual_outputs[1] );

  /* Clone a context for vector 2 */
  mc_mic_md2_clone( & (md2_actual_contexts[7]), & (md2_actual_contexts[0]) );

  /* Hash "abc" (vector 2) */
  mc_mic_md2_update( & (md2_actual_contexts[7]), (uint8_t *) md2_inputs[2], (uint32_t) strlen( (const char *) md2_inputs[2] ) );

  /* Clone the context for vector 2 prior to calling digest */
  mc_mic_md2_clone( & (md2_actual_contexts[8]), & (md2_actual_contexts[7]) );
		     
  /* Produce digest for vector 2 */
  mc_mic_md2_digest( & (md2_actual_contexts[8]), (uint8_t *) md2_actual_outputs[2] );

  /* Clone a context for vector 3 */
  mc_mic_md2_clone( & (md2_actual_contexts[9]), & (md2_actual_contexts[0]) );

  /* Hash "message digest" (vector 3) */
  mc_mic_md2_update( & (md2_actual_contexts[9]), (uint8_t *) md2_inputs[3], (uint32_t) strlen( (const char *) md2_inputs[3] ) );

  /* Clone a context that has been updated with exactly 14 bytes, but not
     finalized */
  mc_mic_md2_clone( & (md2_actual_contexts[10]), & (md2_actual_contexts[9]) );

  /* Clone the context for vector 3 prior to calling digest */
  mc_mic_md2_clone( & (md2_actual_contexts[11]), & (md2_actual_contexts[9]) );

  /* Produce digest for vector 3 */
  mc_mic_md2_digest( & (md2_actual_contexts[11]), (uint8_t *) md2_actual_outputs[3] );

  /* Clone a context for vector 4 */
  mc_mic_md2_clone( & (md2_actual_contexts[12]), & (md2_actual_contexts[0]) );

  /* Hash 16 bytes of "abcdefghijklmnopqrstuvwxyz" (vector 4) */
  mc_mic_md2_update( & (md2_actual_contexts[12]), (uint8_t *) md2_inputs[4], 16 );

  /* Clone a context that has been updated with exactly 16 bytes, but not
     finalized */
  mc_mic_md2_clone( & (md2_actual_contexts[13]), & (md2_actual_contexts[12]) );

  /* Clone a context to use for the rest of vector 4 */
  mc_mic_md2_clone( & (md2_actual_contexts[14]), & (md2_actual_contexts[12]) );

  /* Hash the remainder of vector 4 */
  mc_mic_md2_update( & (md2_actual_contexts[14]), (uint8_t *) & (md2_inputs[4][16]), (uint32_t) strlen( (const char *) &( md2_inputs[4][16] ) ) );

  /* Clone a context that has been updated twice, but not finalized */
  mc_mic_md2_clone( & (md2_actual_contexts[17]), & (md2_actual_contexts[14]) );

  /* Clone the context for vector 4 prior to calling digest */
  mc_mic_md2_clone( & (md2_actual_contexts[15]), & (md2_actual_contexts[14]) );

  /* Produce digest for vector 4 */
  mc_mic_md2_digest( & (md2_actual_contexts[15]), (uint8_t *) md2_actual_outputs[4] );

  /* Clone a context that has been finalized */
  mc_mic_md2_clone( & (md2_actual_contexts[18]), & (md2_actual_contexts[15]) );

  /* Clone a context for vector 5 */
  mc_mic_md2_clone( & (md2_actual_contexts[16]), & (md2_actual_contexts[0]) );

  /* Hash vector 5 */
  mc_mic_md2_update( & (md2_actual_contexts[16]), (uint8_t *) md2_inputs[5], (uint32_t) strlen( (const char *) md2_inputs[5] ) );

  /* Produce digest for vector 5 */
  mc_mic_md2_digest( & (md2_actual_contexts[16]), (uint8_t *) md2_actual_outputs[5] );

  /* Clone a context for vector 6 */
  mc_mic_md2_clone( & (md2_actual_contexts[16]), & (md2_actual_contexts[0]) );

  /* Hash vector 6 */
  mc_mic_md2_update( & (md2_actual_contexts[16]), (uint8_t *) md2_inputs[6], (uint32_t) strlen( (const char *) md2_inputs[6] ) );

  /* Produce digest for vector 6 */
  mc_mic_md2_digest( & (md2_actual_contexts[16]), (uint8_t *) md2_actual_outputs[6] );

  /* Clear context 16 */
  mc_mic_md2_clear( & (md2_actual_contexts[16]) );

  /* Clone a context that's been cleared */
  mc_mic_md2_clone( & (md2_actual_contexts[19]), &(md2_actual_contexts[16]) );

  return( 0 );
}

/** \fn void test_md2_rfc_vectors( void )
**  \brief Tests for compatibility with test vectors provided in RFC1319
** 
** During the init function's run, we hashed a number of "canonical" test
** vectors listed  in RFC1319.  In this function,  we simply  compare the
** results  of our  computation (in  the actual_outputs  array)  with the
** known-good values given in the RFC (in the outputs array).
*/

void test_md2_rfc_vectors( ) {

  CU_ASSERT_EQUAL( 0, memcmp( md2_outputs[0], md2_actual_outputs[0], 16 ) );
  CU_ASSERT_EQUAL( 0, memcmp( md2_outputs[1], md2_actual_outputs[1], 16 ) );
  CU_ASSERT_EQUAL( 0, memcmp( md2_outputs[2], md2_actual_outputs[2], 16 ) );
  CU_ASSERT_EQUAL( 0, memcmp( md2_outputs[3], md2_actual_outputs[3], 16 ) );
  CU_ASSERT_EQUAL( 0, memcmp( md2_outputs[4], md2_actual_outputs[4], 16 ) );
  CU_ASSERT_EQUAL( 0, memcmp( md2_outputs[5], md2_actual_outputs[5], 16 ) );
  CU_ASSERT_EQUAL( 0, memcmp( md2_outputs[6], md2_actual_outputs[6], 16 ) );
}

/** \fn void test_mc_mic_md2_clone( void )
**  \brief Tests our ability to clone hash contexts
** 
** In this  test, we  look to  see if our  ability to  copy a  context is
** dependent on  the state of the  context. I would be  very surprised if
** this fails.
*/

void test_mc_mic_md2_clone( ) {
  /* Can we clone a newly initialized context? */
  CU_ASSERT_EQUAL( 0, memcmp( & (md2_actual_contexts[0]), & (md2_actual_contexts[1]), sizeof( tMCMd2 ) ) );

  /* Can we clone a context that's been updated with less than one block? */
  CU_ASSERT_EQUAL( 0, memcmp( & (md2_actual_contexts[4]), & (md2_actual_contexts[5]), sizeof( tMCMd2 ) ) );
  
  /* Can we clone a context that's processed 14 bytes? */
  CU_ASSERT_EQUAL( 0, memcmp( & (md2_actual_contexts[9]), & (md2_actual_contexts[10]), sizeof( tMCMd2 ) ) );

  /* Can we clone a context that's processed 16 bytes? */
  CU_ASSERT_EQUAL( 0, memcmp( & (md2_actual_contexts[12]), & (md2_actual_contexts[13]), sizeof( tMCMd2 ) ) );

  /* Can we clone a context that's called update twice? */
  CU_ASSERT_EQUAL( 0, memcmp( & (md2_actual_contexts[14]), & (md2_actual_contexts[17]), sizeof( tMCMd2 ) ) );

  /* Can we clone a context that's been finalized? */
  CU_ASSERT_EQUAL( 0, memcmp( & (md2_actual_contexts[15]), & (md2_actual_contexts[18]), sizeof( tMCMd2 ) ) );

  /* Can we clone a context that's been cleared? */
  CU_ASSERT_EQUAL( 0, memcmp( & (md2_actual_contexts[0]), & (md2_actual_contexts[19]), sizeof( tMCMd2 ) ) );
}

/** \fn void test_mc_mic_md2_clear( void )
**  \brief Tests to ensure that sensitive data is cleared
** 
** We test  the mc_mic_md2_clear() function  by comparing the state  of a
** MD2 context  after a  call to mc_mic_md2_clear()  with the state  of a
** context  after a  call to  mc_mic_md2_initialize(). If  they're equal,
** then we're good.
*/

void test_mc_mic_md2_clear( ) {
  /* Compare context 0 (newly initialized) with context 16 (newly cleared) */
  CU_ASSERT_EQUAL( 0, memcmp( & (md2_actual_contexts[0]), & (md2_actual_contexts[16]), sizeof( tMCMd2 ) ) );
}

/** \fn void test_mc_mic_md2_initialize( void )
**  \brief Tests the ability to initiailze a newly allocated hashing context. 
** 
** Testing the initial state of an MD2 context is easy. Everything should
** be zero. If not, then our initialize function is suspect.
*/

void test_mc_mic_md2_initialize( ) {
  uint8_t test_data[ sizeof( tMCMd2 ) ];

  memset( test_data, 0, sizeof( tMCMd2 ) );

  /* For MD2, everything is zeroed out after initialize. */
  CU_ASSERT_EQUAL( 0, memcmp( & (md2_actual_contexts[0]), test_data, sizeof( tMCMd2 ) ) );
}

/** \fn void test_mc_mic_md2_update( void )
**  \brief Tests the hash update function
** 
** Testing  the update  function is  fairly straight-forward.  We  have a
** series  of  known-good values  for  MD2  contexts  at different  times
** throught the hashing  process. We simply compare the  test states with
** the known good values.
*/

void test_mc_mic_md2_update( ) {
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[0] ), (uint8_t *) &( md2_contexts[0] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[1] ), (uint8_t *) &( md2_contexts[1] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[2] ), (uint8_t *) &( md2_contexts[2] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[3] ), (uint8_t *) &( md2_contexts[3] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[4] ), (uint8_t *) &( md2_contexts[4] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[5] ), (uint8_t *) &( md2_contexts[5] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[6] ), (uint8_t *) &( md2_contexts[6] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[7] ), (uint8_t *) &( md2_contexts[7] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[8] ), (uint8_t *) &( md2_contexts[8] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[9] ), (uint8_t *) &( md2_contexts[9] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[10] ), (uint8_t *) &( md2_contexts[10] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[11] ), (uint8_t *) &( md2_contexts[11] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[12] ), (uint8_t *) &( md2_contexts[12] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[13] ), (uint8_t *) &( md2_contexts[13] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[14] ), (uint8_t *) &( md2_contexts[14] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[15] ), (uint8_t *) &( md2_contexts[15] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[16] ), (uint8_t *) &( md2_contexts[16] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[17] ), (uint8_t *) &( md2_contexts[17] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[18] ), (uint8_t *) &( md2_contexts[18] ), sizeof( tMCMd2 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( md2_actual_contexts[19] ), (uint8_t *) &( md2_contexts[19] ), sizeof( tMCMd2 ) ) );
}
